home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume5 / malloc.uport < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  24.6 KB

  1. Path: xanth!nic.MR.NET!hal!ncoast!allbery
  2. From: mike@cimcor.UUCP (Michael Grenier)
  3. Newsgroups: comp.sources.misc
  4. Subject: v05i048: m286 - Fast malloc for Microport
  5. Message-ID: <8811090753.AA19261@cimcor.MN.ORG>
  6. Date: 15 Nov 88 00:24:36 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: mike@cimcor.UUCP (Michael Grenier)
  9. Lines: 908
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 5, Issue 48
  13. Submitted-by: "Michael Grenier" <mike@cimcor.UUCP>
  14. Archive-name: malloc.uport
  15.  
  16. Brandon,
  17.    Here is a fast malloc package for Microport V/AT which performs
  18. at least 10 times faster than malloc(3C). As an example, on this
  19. Microport Version 2.3 system, it does the simple memory allocation 
  20. test about 150 times faster than malloc(3X). Hopefully, someone will
  21. send me the bechmarks comparing it to version 2.4.
  22.  
  23. This package makes heavy use of the Intel 80286 architecture and
  24. is thus not very portable. XENIX people may be able to use it though
  25. their malloc may perform reasonably well.
  26.  
  27.     -Mike Grenier
  28.     mike@cimcor.mn.org
  29.     rutgers!bungia!cimcor!mike
  30.     uunet!rosevax!cimcor!mike
  31.  
  32. #! /bin/sh
  33. # This is a shell archive, meaning:
  34. # 1. Remove everything above the #! /bin/sh line.
  35. # 2. Save the resulting text in a file.
  36. # 3. Execute the file with /bin/sh (not csh) to create:
  37. #    README
  38. #    Makefile
  39. #    malloc.c
  40. #    m286.3x
  41. #    t.c
  42. #    tcheck.c
  43. # This archive created: Wed Nov  9 07:44:21 1988
  44. export PATH; PATH=/bin:/usr/bin:$PATH
  45. echo shar: "extracting 'README'" '(1546 characters)'
  46. if test -f 'README'
  47. then
  48.     echo shar: "will not over-write existing file 'README'"
  49. else
  50. sed 's/^    X//' << \SHAR_EOF > 'README'
  51.     X    m286 - fast malloc for Microport 286
  52.     X    Michael Grenier   11/8/88
  53.     X
  54.     XA couple quick notes on m286 :
  55.     X    - Binaries of this package were sent out via comp.unix.microport some
  56.     X    months ago. It has since been modified slightly to include
  57.     X    limited checking for bad pointers in free().
  58.     X
  59.     X    - m286 seems to perform about 10 to 50 times faster than malloc(3C)
  60.     X    under Microport version 2.3 and earlier. I haven't had a chance to
  61.     X    benchmark it against v2.4 using malloc(3X)...hopefully someone will
  62.     X    send me the tests results.
  63.     X
  64.     X    - This package makes heavy use of the Intel 80286 processor 
  65.     X    specifics. It might be portable to XENIX provided the brk()
  66.     X    system call always returns a new segment as it does under
  67.     X    Microport. Of course, malloc under XENIX may already perform
  68.     X    reasonably well.
  69.     X
  70.     X    - The algorithm is based on the boundary tag system presented
  71.     X    in the book Fundamentals of Data Structures written by
  72.     X    Sahni and Horowitz.
  73.     X
  74.     X    -Please send me bug reports!! mike@cimcor.mn.org
  75.     X
  76.     X
  77.     XHere are the test results from my 8 Mhz 1 wait state machine. The
  78.     Xreal time is significant as these test were run on an otherwise quiet
  79.     Xmachine. The big time difference seems to be due to the OS swapping
  80.     Xprocesses for every brk() system call.
  81.     X
  82.     XBeginning test of standard malloc(3C) for allocating 400K bytes
  83.     Xreal     2:06.1
  84.     Xuser       37.6
  85.     Xsys        14.3
  86.     X
  87.     XBeginning test of standard malloc(3X) for allocating 400K bytes
  88.     Xreal    21:39.6
  89.     Xuser        1.0
  90.     Xsys         3.0
  91.     X
  92.     XBeginning test of standard m286(3X) for allocating 400K bytes
  93.     Xreal        8.4
  94.     Xuser        1.2
  95.     Xsys         1.6
  96. SHAR_EOF
  97. if test 1546 -ne "`wc -c < 'README'`"
  98. then
  99.     echo shar: "error transmitting 'README'" '(should have been 1546 characters)'
  100. fi
  101. fi
  102. echo shar: "extracting 'Makefile'" '(1446 characters)'
  103. if test -f 'Makefile'
  104. then
  105.     echo shar: "will not over-write existing file 'Makefile'"
  106. else
  107. sed 's/^    X//' << \SHAR_EOF > 'Makefile'
  108.     X# Simple Makefile for fast malloc library
  109.     X#
  110.     X# For Microport do:
  111.     X#       make lib
  112.     X#      su root
  113.     X#    make install
  114.     X#
  115.     X# To try out the test programs do :
  116.     X#
  117.     X#    make tests
  118.     X#
  119.     X# Tests results are placed in the file 't-results'
  120.     X#
  121.     XCFLAGS= -Ml -O
  122.     XCC=cc
  123.     XLIBDIR=/usr/lib/large
  124.     Xlib : malloc.o
  125.     X    ar rv libm286.a malloc.o
  126.     Xinstall : libm286.a
  127.     X    mv libm286.a $(LIBDIR)
  128.     X    chmod 644 $(LIBDIR)/libm286.a
  129.     X    chgrp bin $(LIBDIR)/libm286.a
  130.     X    chown bin $(LIBDIR)/libm286.a
  131.     Xmalloc.o : /usr/include/malloc.h
  132.     X    $(CC) $(CFLAGS) -c malloc.c
  133.     X
  134.     Xtests : t-m286 tc-m286 $(LIBDIR)/libm286.a
  135.     X    @echo 'Beginning tests .... This will take awhile'
  136.     X    @echo 'Beginning test of standard malloc(3C) for allocating 400K bytes'
  137.     X    @echo 'Beginning test of standard malloc(3C) for allocating 400K bytes' >t-results
  138.     X    time t-malloc 400 2>>t-results
  139.     X    @echo 'Beginning test of standard malloc(3X) for allocating 400K bytes' >>t-results
  140.     X    @echo 'Beginning test of standard malloc(3X) for allocating 400K bytes'
  141.     X    -time t-malloc3x 400 2>>t-results
  142.     X    @echo 'Beginning test of standard m286(3X) for allocating 400K bytes' >>t-results
  143.     X    @echo 'Beginning test of standard m286(3X) for allocating 400K bytes' 
  144.     X    time t-m286 400 2>>t-results
  145.     X    
  146.     Xt-m286 : t.o
  147.     X    $(CC) $(CFLAGS) -o t-m286 t.o -lm286
  148.     X    $(CC) $(CFLAGS) -o t-malloc t.o
  149.     X    $(CC) $(CFLAGS) -o t-malloc3x t.o -lmalloc
  150.     X 
  151.     Xtc-m286 : tcheck.o
  152.     X    $(CC) $(CFLAGS) -o tc-m286 tcheck.o -lm286
  153.     X    $(CC) $(CFLAGS) -o tc-malloc tcheck.o
  154.     X    $(CC) $(CFLAGS) -o tc-malloc3x tcheck.o -lmalloc
  155.     X 
  156.     X
  157. SHAR_EOF
  158. if test 1446 -ne "`wc -c < 'Makefile'`"
  159. then
  160.     echo shar: "error transmitting 'Makefile'" '(should have been 1446 characters)'
  161. fi
  162. fi
  163. echo shar: "extracting 'malloc.c'" '(12693 characters)'
  164. if test -f 'malloc.c'
  165. then
  166.     echo shar: "will not over-write existing file 'malloc.c'"
  167. else
  168. sed 's/^    X//' << \SHAR_EOF > 'malloc.c'
  169.     X
  170.     X/*
  171.     X        Fast Malloc for Microport 286
  172.     X        Copyright (C) April 1988
  173.     X        Michael Grenier
  174.     X
  175.     XPermission to redistribute for non-profit use is hereby granted.
  176.     XPlease send bug fixes to mike@cimcor.mn.org
  177.     X
  178.     X*/
  179.     X#include <stdio.h>
  180.     X#include <memory.h>
  181.     X
  182.     X/*  TUNABLE PARAMETERS */
  183.     X
  184.     X
  185.     X#define EPSILON        10  /* Blocks smaller than this number of words are not
  186.     X                retained */
  187.     X
  188.     X
  189.     X/* DO NOT CHANGE! */
  190.     X#define ALLOCATED    1
  191.     X#define AVAILABLE    0
  192.     X#define MAX_BLOCK_SIZE 32744          /* maximum size block we can allocate -
  193.     X                        32768 - 4 * HEADER_SIZE  words */
  194.     X#define LLINK(x)    (page[x])    /* pointer to previous block in page */
  195.     X#define TAG(x)        (page[x+1])  /* set to 1 if allocated */
  196.     X#define SIZE(x)        (page[x+2])  /* Number of words in this block not counting header */
  197.     X#define RLINK(x)    (page[x+3])  /* pointer to next block */
  198.     X#define ETAG(x)        (page[x+SIZE(x)+4])  /* set to 1 if allocated */
  199.     X#define ULINK(x)    (page[x+SIZE(x)+5])  /* pointer to beginning of this block */
  200.     X#define AV(indx)    (av_list[indx])      /* pointer to block on free list with this page */
  201.     X
  202.     Xstatic char *xxcopyright="\n\n\nCopyright 1988 by Michael Grenier, all rights reserved\n\n";
  203.     X
  204.     Xchar *sbrk();   /* needed Unix System calls */
  205.     Xint    brk();
  206.     X
  207.     Xstatic unsigned av_list[62],   /* offset pointer to a free block with each page */
  208.     X     m_curindx=0,    /* Current page to allocate from */
  209.     X     free_indx=1;    /* Page to begin searching for a block in */
  210.     X
  211.     Xstatic int xxfunny[4]={23,56,12,23}; /* used to uniquely identify this binary should
  212.     X                someone steal the start distributing binaries
  213.     X                and delete the copyright */
  214.     X
  215.     X#define HEADER_SIZE    6 /* words wasted per block */
  216.     X#define ALLOCATE_OFFSET 4 /* Offset in block where user process pointer points */
  217.     X
  218.     Xstatic long m_endds, m_first_endds; /* address of current and initial brk() value */
  219.     X
  220.     X
  221.     X/* Get starting address of this segment given segment number
  222.     X   starting with one as the first segment allocated
  223.     X*/
  224.     Xunsigned int *getpage(indx)
  225.     Xunsigned indx;
  226.     X{
  227.     X    return (unsigned int *) ((m_first_endds + ((unsigned long)indx - 1L)
  228.     X         * 0x00080000L) & 0xFFFF0000L); /* adjust selector */
  229.     X}
  230.     X
  231.     X
  232.     X
  233.     X/* can't use stock memcpy, memset as they don't handle a size
  234.     X    greater than 32K bytes */
  235.     X
  236.     Xvoid u_memset(ptr, value, size) /* in words */
  237.     Xunsigned int *ptr, value, size;
  238.     X{
  239.     X    while (!size)
  240.     X    {
  241.     X        (*(ptr++)) = value;
  242.     X        size--;
  243.     X    }
  244.     X}
  245.     X
  246.     Xvoid u_memcpy(ptr1, ptr2, size) /* in words, should be written in asssembler ti use block moves */
  247.     Xunsigned int *ptr1, *ptr2, size;
  248.     X{
  249.     X    while (!size)
  250.     X    {
  251.     X        (*(ptr1++)) = *(ptr2++);
  252.     X        size--;
  253.     X    }
  254.     X}
  255.     X
  256.     X
  257.     X/*
  258.     X    New_page() - allocate a new segment from Unix
  259.     X    This routine allocates a full 64K segment to be supplied to malloc
  260.     X    to be split up as appropiate
  261.     X*/
  262.     Xvoid new_page()
  263.     X{
  264.     X    unsigned temp, *page;
  265.     X    
  266.     X    if (m_curindx==0) /* First time so initialize a segment */
  267.     X    {
  268.     X        m_first_endds = (long) sbrk(0);  /* returns next segment value */
  269.     X        m_endds = m_first_endds + 65535L;
  270.     X    }
  271.     X    else
  272.     X        m_endds += 0x00080000L; /* add one to 80286 selector */
  273.     X
  274.     X    brk((char *) m_endds);    /* allocates the new page (segment) */
  275.     X    
  276.     X    /* Now set up free list in segment. Allocate and tag busy two zero
  277.     X       length blocks on each end of page to simplify and speed up
  278.     X       allocation algorithm - see Sahni's notes. Also allocate a
  279.     X       zero length free segment and set AV to point to it.
  280.     X    */
  281.     X    
  282.     X    m_curindx++;  /* Update number of pages allocated */
  283.     X    page = getpage (m_curindx); /* set up to use macros */
  284.     X    
  285.     X    TAG(0)    = ALLOCATED;  /* allocate zero length block at start of page */
  286.     X    SIZE(0)    = 0;
  287.     X    ETAG(0)    = ALLOCATED;
  288.     X    ULINK(0)= 0;
  289.     X    
  290.     X
  291.     X
  292.     X    temp = 32768 - HEADER_SIZE;/* point to last possible block in page
  293.     X                      and allocate it also */
  294.     X                      
  295.     X    TAG(temp)   = ALLOCATED;
  296.     X    SIZE(temp)  = 0;
  297.     X    ETAG(temp)  = ALLOCATED;
  298.     X    ULINK(temp) = temp;
  299.     X
  300.     X
  301.     X
  302.     X    temp = HEADER_SIZE; /* Now allocate a zero length free block that
  303.     X                   will never get allocated (because of its size) */
  304.     X
  305.     X    TAG(temp)   = AVAILABLE;
  306.     X    SIZE(temp)  = 0;
  307.     X    LLINK(temp) = temp + HEADER_SIZE; /* point to next block (yet to be 
  308.     X                         created) which will be the actual
  309.     X                         free block */
  310.     X    ETAG(temp)  = AVAILABLE;
  311.     X    ULINK(temp) = temp;
  312.     X    RLINK(temp) = temp + HEADER_SIZE;
  313.     X    av_list[m_curindx] = temp;      /* point to first free block */
  314.     X    
  315.     X
  316.     X    temp += HEADER_SIZE;  /* Finally, allocate the actual free block */
  317.     X    TAG(temp) = AVAILABLE;  /* mark as free */
  318.     X    SIZE(temp) = MAX_BLOCK_SIZE;
  319.     X    LLINK(temp) = HEADER_SIZE; /* point to previous free block */
  320.     X    RLINK(temp) = HEADER_SIZE;
  321.     X    ETAG(temp)  = AVAILABLE;
  322.     X    ULINK(temp) = temp;
  323.     X}
  324.     X
  325.     Xunsigned int get_offset(ptr)
  326.     Xunsigned int *ptr; /* not char * because we want pointer math in words, not bytes */
  327.     X{
  328.     X    unsigned int temp = (((unsigned) ptr >>1) - ALLOCATE_OFFSET);
  329.     X    return temp;
  330.     X}
  331.     X
  332.     X
  333.     Xvoid free_from_page(p, seqindx)
  334.     Xunsigned int p, seqindx;
  335.     X{
  336.     X    unsigned int n, q, r, *page;
  337.     X    
  338.     X    /* point to true beginning of block */
  339.     X    
  340.     X    page = getpage(seqindx);
  341.     X
  342.     X    if ((TAG(p) != ALLOCATED) || (ETAG(p) != ALLOCATED))
  343.     X    {
  344.     X        fprintf(stderr,"\n\rAttempt to free a pointer which was not allocated\n");
  345.     X        fprintf(stderr,"or had its control block information overwritten!\n");
  346.     X        abort();
  347.     X    }
  348.     X
  349.     X    n = SIZE(p);
  350.     X
  351.     X    if (((p==12) || (page[p-2]==ALLOCATED))
  352.     X       && (TAG(p+n+HEADER_SIZE)==ALLOCATED))
  353.     X    /* free this block but do not join with neighbors */
  354.     X    {
  355.     X        TAG(p)        = AVAILABLE;
  356.     X        ETAG(p)            = AVAILABLE;
  357.     X        ULINK(p)    = p;
  358.     X        LLINK(p)    = AV(seqindx);
  359.     X        RLINK(p)    = RLINK(AV(seqindx));
  360.     X/*        LLINK(RLINK(p)    = p;        Can't seem to nest macros */
  361.     X        page [ RLINK(p) ] = p;
  362.     X        RLINK(AV(seqindx))    = p;
  363.     X    }
  364.     X    else if ((p!=12) &&    /* Never join with first empty block as AV must point to something */
  365.     X        (page[p-2]==AVAILABLE) && 
  366.     X        ((TAG(p+n+HEADER_SIZE))==ALLOCATED))
  367.     X    /* join with left block */
  368.     X    {
  369.     X        q = page[p-1]; /* start of left block */
  370.     X        SIZE(q) = SIZE(q) + n + HEADER_SIZE;
  371.     X        ULINK(p) = q;
  372.     X        ETAG(p)  = AVAILABLE;
  373.     X        AV(seqindx) = q;     /* always leave AV pointing to possible full block */
  374.     X    }
  375.     X    else if (((p==12) || (page[p-2]==ALLOCATED)) &&
  376.     X        ((TAG(p+n+HEADER_SIZE))==AVAILABLE))
  377.     X    /* join with right block */
  378.     X    {
  379.     X        q = p + n + HEADER_SIZE; /* start of next block */
  380.     X        page[ page[q] + 3] = p;  /* RLINK(LLINK(q))=p  stupid macros...*/ 
  381.     X        page[page[q+3]]=p;   /*LLINK(RLINK(q)) = p; */
  382.     X        LLINK(p) = LLINK(q);
  383.     X        RLINK(p) = RLINK(q);
  384.     X        SIZE(p) = n + HEADER_SIZE + SIZE(q);
  385.     X        ULINK(p) = p;
  386.     X        TAG(p) = AVAILABLE;
  387.     X        AV(seqindx)=p; /* Can't have free list pointer pointing to 
  388.     X                    garbage! */
  389.     X    }
  390.     X    else 
  391.     X    {
  392.     X        /* join with both sides */
  393.     X        q = p + n + HEADER_SIZE; /* start of next block */
  394.     X        r = page[p - 1];      /* start of previous block */
  395.     X        RLINK(LLINK(q))=RLINK(q);
  396.     X        LLINK(RLINK(q))=LLINK(q);
  397.     X        SIZE(r)=SIZE(r) + (n + HEADER_SIZE) + SIZE(q) + HEADER_SIZE;
  398.     X        ULINK(r)=r;
  399.     X        AV(seqindx)=r; /* don't point to garbage */
  400.     X    }
  401.     X}
  402.     X
  403.     X
  404.     X
  405.     Xunsigned int *allocate_from_page(n, seqindx)
  406.     Xunsigned int n, seqindx;
  407.     X{
  408.     X    unsigned int p, diff, *page;
  409.     X    page = getpage(seqindx);
  410.     X    p = AV(seqindx); /* point to first free block */
  411.     X    do
  412.     X    {    /* search for a free block, first fit */
  413.     X        if (SIZE(p) >= n)  /* allocate it */
  414.     X        {
  415.     X            diff=SIZE(p)-n;
  416.     X            if (diff < EPSILON) /* allocate whole block */
  417.     X            {
  418.     X                RLINK(LLINK(p)) = RLINK(p);
  419.     X                LLINK(RLINK(p)) = LLINK(p);
  420.     X                TAG(p)  = ALLOCATED;
  421.     X                ETAG(p) = ALLOCATED;
  422.     X                AV(seqindx) = LLINK(p);
  423.     X                return(page + p + ALLOCATE_OFFSET);
  424.     X            }
  425.     X            else
  426.     X            {    /* free lower portion of block */
  427.     X                SIZE(p)  = diff - HEADER_SIZE; /* remaining free portion */
  428.     X                ULINK(p) = p;
  429.     X                ETAG(p)  = AVAILABLE;
  430.     X                AV(seqindx) = p;
  431.     X                
  432.     X                /* allocate the rest of block */
  433.     X                p += SIZE(p) + HEADER_SIZE; /* point to start of block */
  434.     X                SIZE(p) = n;
  435.     X                TAG(p)  = ALLOCATED;
  436.     X                ETAG(p) = ALLOCATED;
  437.     X                ULINK(p) = p;
  438.     X                return (page + p + ALLOCATE_OFFSET);
  439.     X            }
  440.     X        }
  441.     X        p = RLINK(p); /* point to next free block */
  442.     X    } while (p != AV(seqindx));
  443.     X    return ((unsigned int *) 0);
  444.     X}
  445.     X
  446.     X
  447.     Xvoid return_free_pages()
  448.     X{
  449.     X    unsigned i, *page; /* leave one page allocated because this
  450.     X            #*#*!& UNIX won't give you the intial brk value */
  451.     X    while ((m_curindx>1) && (page=getpage(m_curindx),
  452.     X            SIZE(AV(m_curindx)) == MAX_BLOCK_SIZE))
  453.     X    {
  454.     X        m_curindx--;
  455.     X        m_endds -= 0x00080000L; /* subtract one from selector */
  456.     X    };
  457.     X    brk( (char *) m_endds);
  458.     X}
  459.     X
  460.     X
  461.     Xchar *malloc(size)
  462.     Xunsigned size;
  463.     X{
  464.     X    char *dummy;
  465.     X    int indx;
  466.     X
  467.     X    if (m_curindx==0)
  468.     X        if (!new_page()) return((char *) 0); /* no more memory */
  469.     X    
  470.     X    /* calculate page address */
  471.     X
  472.     X    indx=free_indx;
  473.     X    do
  474.     X    {
  475.     X        if ((dummy = (char *) allocate_from_page((size+1)>>1, indx))
  476.     X            !=NULL) 
  477.     X        {
  478.     X            free_indx=indx; /* to speed up allocating for next malloc */
  479.     X            return ((char *) dummy);
  480.     X        }            
  481.     X        indx++;
  482.     X        if (indx>m_curindx) indx=1;
  483.     X    } while (indx != free_indx);
  484.     X
  485.     X/*  -- if we haven't returned yet, call brk for more memory and try again */
  486.     X
  487.     X    if (!new_page()) return((char *) 0);
  488.     X    return((char *) allocate_from_page((size+1)>>1, m_curindx));
  489.     X    
  490.     X}
  491.     X
  492.     X
  493.     Xchar *calloc(nelem, elsize)
  494.     Xunsigned nelem, elsize;
  495.     X{
  496.     X    char *dum;
  497.     X    register unsigned size;
  498.     X    size = nelem*elsize; /* in bytes, assume compiler word aligns structures */
  499.     X    if ((dum=malloc(size)) != NULL)   /* zero out the block */
  500.     X        u_memset( (int *) dum, 0, size>>1); /* set size words to 0 */
  501.     X    return dum;
  502.     X}
  503.     X
  504.     X
  505.     Xvoid free(ptr)
  506.     Xchar *ptr;
  507.     X{
  508.     X    unsigned int indx;
  509.     X    long temp;
  510.     X
  511.     X    temp = (long) ptr - m_first_endds;
  512.     X    indx = (temp >>19) + 1;        /* get selector for pointer */
  513.     X    free_from_page(get_offset((unsigned int *)ptr), indx);
  514.     X    return_free_pages();
  515.     X}
  516.     X
  517.     X
  518.     X
  519.     Xchar *realloc( ptr, size)
  520.     Xchar *ptr;
  521.     Xunsigned size;
  522.     X{
  523.     X    unsigned int seqindx, *page, rb, p, diff;
  524.     X    long temp;
  525.     X    char * ptrnew;
  526.     X
  527.     X    if (size==0) 
  528.     X    {
  529.     X        free(ptr);
  530.     X        return (char *) NULL; 
  531.     X    }
  532.     X    
  533.     X    temp = (long) ptr - m_first_endds;
  534.     X    seqindx = (temp >>19) + 1;        /* get selector for pointer */
  535.     X    
  536.     X    page = getpage(seqindx);
  537.     X    p = get_offset((unsigned int *) ptr);
  538.     X    size = (size + 1) >>1;                /* bytes to words, round up */
  539.     X    diff =  SIZE(p) - size;     /* in words */
  540.     X    if (size <= SIZE(p)) /* words, reduce space */
  541.     X    {
  542.     X        unsigned int rbnew;
  543.     X
  544.     X        if (diff<HEADER_SIZE)
  545.     X            return ptr;    /* if can't create a new free block then */
  546.     X                    /* waste the few bytes */
  547.     X            
  548.     X        SIZE(p) -= diff;        /* modify this block */
  549.     X        ULINK(p) =p;
  550.     X        ETAG(p)  = ALLOCATED;
  551.     X
  552.     X        rbnew = p + HEADER_SIZE + SIZE(p); /* build new right block */
  553.     X        TAG(rbnew) = ALLOCATED;
  554.     X        SIZE(rbnew) = diff - HEADER_SIZE;
  555.     X        ETAG(rbnew) = ALLOCATED;
  556.     X        ULINK(rbnew) = rbnew;
  557.     X        free_from_page(rbnew, seqindx);
  558.     X        return(ptr);
  559.     X    }
  560.     X
  561.     X    /* enlarging space */
  562.     X
  563.     X    rb=p+SIZE(p)+HEADER_SIZE; /* see if space is available from next block*/
  564.     X    diff= -diff;
  565.     X    if ((TAG(rb)==AVAILABLE) && ((SIZE(rb)+1)>diff))
  566.     X    {    /* take from right block - save important info */
  567.     X        unsigned int lsave, rsave, ssave;
  568.     X        lsave=LLINK(rb);
  569.     X        rsave=RLINK(rb);
  570.     X        ssave=SIZE(rb);
  571.     X        SIZE(p)  = size;
  572.     X        ULINK(p) = p;
  573.     X        ETAG(p)  = ALLOCATED;
  574.     X        rb = p + SIZE(p) + HEADER_SIZE;
  575.     X        
  576.     X        /* fix right block */
  577.     X        
  578.     X        LLINK(rb) = lsave;
  579.     X        RLINK(rb) = rsave;
  580.     X        TAG(rb)   = AVAILABLE;
  581.     X        SIZE(rb)  = ssave - diff;
  582.     X        ETAG(rb)  = AVAILABLE; /* shouldn't have changed but ... */
  583.     X        ULINK(rb) = rb;
  584.     X        
  585.     X        /* fix neighbors on free list */
  586.     X        LLINK(RLINK(rb)) = rb;
  587.     X        RLINK(LLINK(rb)) = rb;
  588.     X        return ptr;
  589.     X    }
  590.     X    
  591.     X    /* Finally, if room wasn't availble, allocate new block and move stuff */
  592.     X    
  593.     X    ptrnew = malloc(size<<1);
  594.     X    u_memcpy((int *) ptr, (int *) ptrnew, SIZE(p));
  595.     X    free (ptr);
  596.     X    return ptrnew;
  597.     X        
  598.     X}
  599.     X
  600.     X
  601.     Xchar *tagit(i)
  602.     Xunsigned int i;
  603.     X{
  604.     X    if (i==AVAILABLE)
  605.     X        return "AVAIL ";
  606.     X    if (i==ALLOCATED)
  607.     X        return "IN USE";
  608.     X    return "*BAD* ";
  609.     X}
  610.     X
  611.     X
  612.     Xint dump_malloc()
  613.     X{
  614.     X    unsigned int indx, ptr, *page;
  615.     X    
  616.     X    if (m_curindx==0) 
  617.     X    {
  618.     X        fprintf(stderr,"\r\n No segments allocated\r\n");
  619.     X        return(1);
  620.     X    }
  621.     X    
  622.     X    for (indx=1; indx<=m_curindx; indx++)
  623.     X    {
  624.     X        fprintf(stderr,"\r\n Segment No. %d : \r\n",indx);
  625.     X        page=getpage(indx);
  626.     X        
  627.     X        ptr = 0; /* first block */
  628.     X        fprintf(stderr," Ptr      Block\r\n");
  629.     X        fprintf(stderr," Addr     offset       LLINK  TAG    SIZE    RLINK  ETAG    UPLINK\r\n\n");
  630.     X        while (ptr!=32768 /* last block */ )
  631.     X        {
  632.     X            fprintf(stderr,"%.8lx   %.5u      %.5u  %s  %.5u   %.5u  %s  %.5u \r\n",
  633.     X              page + ptr + ALLOCATE_OFFSET,
  634.     X              ptr, LLINK(ptr), tagit(TAG(ptr)), SIZE(ptr), RLINK(ptr), 
  635.     X                       tagit(ETAG(ptr)), ULINK(ptr));
  636.     X              
  637.     X            ptr += HEADER_SIZE+SIZE(ptr);
  638.     X            if (ptr<6) abort();
  639.     X        }
  640.     X        
  641.     X        fprintf(stderr," \r\n AV points to %u\r\n\n",AV(indx));
  642.     X    }
  643.     X    return(1);
  644.     X}    
  645.     X
  646.     X
  647.     X/* int check_malloc()
  648.     X{
  649.     X    char pointers[32762]; 
  650.     X    unsigned int first, cur, indx, *page;
  651.     X    
  652.     X    for (indx=1; indx<=m_curindx; indx++);
  653.     X    {
  654.     X        fprintf("\nChecking segment %d for LLINKS\n", indx);
  655.     X        for (cur==0; cur<32762; cur++)
  656.     X            pointers[cur]=0;
  657.     X        page=getpage(indx);
  658.     X        first=AV(indx);
  659.     X        cur=first;
  660.     X        while (pointers[cur]==0)
  661.     X        {
  662.     X            pointers[cur]=1;
  663.     X            cur=LLINK(cur);
  664.     X        }
  665.     X        if (cur != first)abort();
  666.     X        
  667.     X        fprintf("\nChecking segment %d for RLINKS\n", indx);
  668.     X        for (cur==0; cur<32760; cur++)
  669.     X            pointers[cur]=0;
  670.     X        page=getpage(indx);
  671.     X        first=AV(indx);
  672.     X        cur=first;
  673.     X        while (pointers[cur]==0)
  674.     X        {
  675.     X            pointers[cur]=1;
  676.     X            cur=RLINK(cur);
  677.     X        }
  678.     X        if (cur != first)abort();
  679.     X    }
  680.     X}
  681.     X*/
  682. SHAR_EOF
  683. if test 12693 -ne "`wc -c < 'malloc.c'`"
  684. then
  685.     echo shar: "error transmitting 'malloc.c'" '(should have been 12693 characters)'
  686. fi
  687. fi
  688. echo shar: "extracting 'm286.3x'" '(2318 characters)'
  689. if test -f 'm286.3x'
  690. then
  691.     echo shar: "will not over-write existing file 'm286.3x'"
  692. else
  693. sed 's/^    X//' << \SHAR_EOF > 'm286.3x'
  694.     X.TH M286 3X
  695.     X.SH NAME
  696.     Xm286 \- malloc package for iAPX286 processor
  697.     X.SH SYNOPSIS
  698.     X.nf
  699.     X    char *malloc(size)
  700.     X    unsigned size;
  701.     X
  702.     X    void free(ptr)
  703.     X    char *ptr;
  704.     X
  705.     X    char *realloc(ptr, size)
  706.     X    char *ptr;
  707.     X    unsigned size;
  708.     X
  709.     X    char calloc(nelem, elsize)
  710.     X    unsigned nelem, elsize;
  711.     X
  712.     X    int dump_malloc()
  713.     X.fi
  714.     X.SH DESCRIPTION
  715.     X.I M286
  716.     Xis a malloc(3C) compatible library designed for use on the iAPX286 processor.
  717.     XPerformance is greatly improved over both malloc(3C) and malloc(3X) by
  718.     Xallocating full 64K segments via the brk() system call and divving up
  719.     Xthe segments as needed, reducing UNIX overhead. Is is found in the library
  720.     X"m286", and is loaded if the option "-lm286" is used with cc(1) or
  721.     Xld(1).
  722.     X
  723.     X.I Malloc
  724.     Xreturns a pointer to a block of at least size bytes.
  725.     X
  726.     X.I Free
  727.     Xreturns the space previously allocated with calloc() or malloc()
  728.     Xas pointed to by the argument
  729.     X.I ptr.
  730.     XContents of the block are preserved until the next malloc() or calloc()
  731.     Xcall.
  732.     X
  733.     X.I Realloc
  734.     Xchanges the size of the blocked pointed to by 
  735.     X.I ptr 
  736.     Xto the size given by argument two in bytes. Contents of the block
  737.     Xwill be unchanged up to either the original size or the new size,
  738.     Xwhichever is smaller.
  739.     X
  740.     X.I Calloc
  741.     Xallocates space via malloc and intializes the space to zeros. The
  742.     Xamount of space allocated is set up to handle an array of 
  743.     X.I nelem
  744.     Xelements of size
  745.     X.I elsize.
  746.     X
  747.     X.I Dump_malloc
  748.     Xprovides a means to debug pointer references by dumping a list of all
  749.     Xblocks within
  750.     X.I m286's
  751.     Xfree list or those currently allocated to the standard error device. The listing
  752.     Xcontains LLINK, RLINK which are pointers to the previous and next blocks
  753.     Xon the free list. TAG and ETAG are flags indicating whether the block is
  754.     Xin use or not. ULINK is always a pointer to the beginning of the block.
  755.     XAll of the fields are displayed as indexes into a array of words within
  756.     Xthe allocated segment.
  757.     X
  758.     X.SH CAVEATS
  759.     XSince performance is gained by allocating full 64K segments, an average
  760.     Xof 32K bytes will be wasted by the process. The maximum size block that
  761.     Xcan be allocated is 65488 bytes. If larger sizes are needed, use brk() directly.
  762.     X
  763.     XThis software is copyright and can only be used and distributed for
  764.     Xnon-commercial use. Commerical licenses can be obtained from
  765.     Xmike@cimcor.mn.org for a very low cost.
  766.     X.SH FILES
  767.     X.DT
  768.     X/usr/lib/large/libm286.a
  769.     X.SH "SEE ALSO"
  770.     Xmalloc(3c), malloc(3x), brk(2)
  771. SHAR_EOF
  772. if test 2318 -ne "`wc -c < 'm286.3x'`"
  773. then
  774.     echo shar: "error transmitting 'm286.3x'" '(should have been 2318 characters)'
  775. fi
  776. fi
  777. echo shar: "extracting 't.c'" '(635 characters)'
  778. if test -f 't.c'
  779. then
  780.     echo shar: "will not over-write existing file 't.c'"
  781. else
  782. sed 's/^    X//' << \SHAR_EOF > 't.c'
  783.     X#include <stdio.h>
  784.     X#include <malloc.h>
  785.     X
  786.     Xmain(argc, argv)
  787.     Xint argc;
  788.     Xchar *argv[];
  789.     X{
  790.     X    char *p;
  791.     X    int size,i,j;
  792.     X    if (argc!=2)
  793.     X    {
  794.     X        printf("%s: Usage - t number \n",argv[0]);
  795.     X        printf(" Where 'number' is the number of kilobytes to allocate\n");
  796.     X        exit(1);
  797.     X    }
  798.     X
  799.     X    if ((size=atoi(argv[1])) == 0)
  800.     X    {
  801.     X        printf("%s: Bad argument, must be integer in kilobytes",argv[0]);
  802.     X        exit(1);
  803.     X    }
  804.     X    
  805.     X    for (i=0; i<size; i++)
  806.     X        for (j=0; j<10; j++)
  807.     X            if ((p=malloc(100))==NULL)
  808.     X            {
  809.     X                printf("\nNot enough memory available\n");
  810.     X                printf("Was only able to allocate %ld bytes",i*1024L+j*100L);
  811.     X                exit(2);
  812.     X            } else putchar('.');
  813.     X    putchar('\n');
  814.     X    return 0;
  815.     X}
  816. SHAR_EOF
  817. if test 635 -ne "`wc -c < 't.c'`"
  818. then
  819.     echo shar: "error transmitting 't.c'" '(should have been 635 characters)'
  820. fi
  821. fi
  822. echo shar: "extracting 'tcheck.c'" '(1564 characters)'
  823. if test -f 'tcheck.c'
  824. then
  825.     echo shar: "will not over-write existing file 'tcheck.c'"
  826. else
  827. sed 's/^    X//' << \SHAR_EOF > 'tcheck.c'
  828.     X#include <stdio.h>
  829.     X#include <malloc.h>
  830.     X#include <signal.h>
  831.     Xchar *calloc();
  832.     X
  833.     X#define NSEGS 512   /* must be power of two  - this program allocates
  834.     X            up to NSEGS * 1K bytes            */
  835.     X
  836.     Xchar *p[NSEGS];
  837.     X
  838.     X#ifdef DEBUG
  839.     Xvoid fault(no)
  840.     Xint no;
  841.     X{
  842.     X    fprintf(stderr,"Caught signal number %d\n",no);
  843.     X    dump_malloc();
  844.     X    abort();
  845.     X}
  846.     X#endif
  847.     X
  848.     X
  849.     Xvoid print_pointers()
  850.     X{
  851.     X    int i;
  852.     X    fprintf(stderr,"\n Pointers are : ");
  853.     X    for (i=0; i<NSEGS; i++)
  854.     X        fputc( (p[i]==NULL ? 'F':'T'), stderr);
  855.     X    fputc('\n',stderr);
  856.     X}
  857.     X        
  858.     X
  859.     X
  860.     Xmain(argc, argv)
  861.     Xint argc;
  862.     Xchar *argv[];
  863.     X{
  864.     X    int j,k; 
  865.     X    unsigned s,fill;
  866.     X    long i;
  867.     X
  868.     X#ifdef DEBUG
  869.     X    signal(SIGINT,fault);
  870.     X#endif
  871.     X
  872.     X    for (i=0; i<NSEGS; i++)
  873.     X        p[i]=NULL;
  874.     X
  875.     X    for (i=0; i<100000; i++)
  876.     X    {
  877.     X        k= rand() & (NSEGS - 1); /* choose a pointer */
  878.     X        if (p[k] == NULL)
  879.     X        {
  880.     X            int call_type;
  881.     X/*            print_pointers(); */
  882.     X            s=(unsigned) rand() & 0x3ff;  /* pick a size */
  883.     X            fprintf(stderr," %ld : Allocating a size of %u to pointer %d ",i,s,k);
  884.     X
  885.     X            call_type = rand() & 1;
  886.     X            p[k] = ( call_type ? malloc(s) : calloc(s,1) );
  887.     X            fprintf(stderr,"and getting %lx using %s\n",
  888.     X                p[k], ( call_type ? "malloc" : "calloc"));
  889.     X            for (fill=0; fill<s; fill++)  /* fill the buffer */
  890.     X                p[k] [fill] = (char) (i & 0xff);
  891.     X
  892.     X        }
  893.     X        j=rand() & (NSEGS-1);   /* choose another pointer */
  894.     X        if (p[j] != NULL)
  895.     X        {
  896.     X            fprintf(stderr," %ld : freeing %lx from pointer %d\n",i,p[j],j);
  897.     X            free(p[j]);
  898.     X            p[j]=NULL;
  899.     X        }
  900.     X
  901.     X        j=rand() & (NSEGS-1);
  902.     X        if (p[j] != NULL)
  903.     X        {
  904.     X            s=rand()&0x3ff;
  905.     X            fprintf(stderr," %ld : realloc %lx to size %d on pointer %d\n", 
  906.     X                i, p[j], s,j);
  907.     X            p[j]=realloc(p[j], s);
  908.     X        }
  909.     X
  910.     X    }
  911.     X}
  912. SHAR_EOF
  913. if test 1564 -ne "`wc -c < 'tcheck.c'`"
  914. then
  915.     echo shar: "error transmitting 'tcheck.c'" '(should have been 1564 characters)'
  916. fi
  917. fi
  918. exit 0
  919. #    End of shell archive
  920.